package com.think.cloud.thinkshop.mall.service.verificationcode.impl;

import cn.hutool.core.util.RandomUtil;
import com.think.cloud.thinkshop.mall.controller.admin.message.dto.MessageTemplateReplaceDTO;
import com.think.cloud.thinkshop.mall.domain.memberuser.MemberUser;
import com.think.cloud.thinkshop.mall.enums.message.MessageTemplateEnum;
import com.think.cloud.thinkshop.mall.service.email.EmailService;
import com.think.cloud.thinkshop.mall.service.memberuser.IMemberUserService;
import com.think.cloud.thinkshop.mall.service.message.IMessageTemplateService;
import com.think.cloud.thinkshop.mall.service.verificationcode.VerificationCodeService;
import com.think.common.core.constant.VerificationCodeConstant;
import com.think.common.core.exception.util.ServiceExceptionUtil;
import com.think.common.redis.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.think.common.core.exception.enums.ErrorCode.*;

/**
 * @author zkthink
 * @apiNote
 **/
@Service
public class VerificationCodeServiceImpl implements VerificationCodeService {
    @Autowired
    private EmailService emailService;
    @Autowired
    private IMemberUserService userService;
    @Autowired
    public RedisService redisService;
    @Autowired
    private IMessageTemplateService messageTemplateService;

    @Override
    public boolean sendEmailCode(String email) {
        //查询是否存在
        MemberUser user = userService.getByEmail(email);
        if (Objects.nonNull(user)) {
            throw ServiceExceptionUtil.exception(EMAIL_REGISTERED);
        }
        String keyPrefix = VerificationCodeConstant.VERIFICATION_CODE_REGISTER_KEY;
        //查询验证码是否存在,防止重复发送
        checkIsExist(keyPrefix, email);
        //生成验证码
        String code = genCode();

        MessageTemplateReplaceDTO param = MessageTemplateReplaceDTO.builder()
                .email(email)
                .code(code)
                .build();
        if (messageTemplateService.sendMessageText(MessageTemplateEnum.TEMPLATE_1, param,email)) {
            cache(keyPrefix, email, code);
            return true;
        }
        return false;
    }

    @Override
    public void sendEmailCodeForget(String email) {
        String keyPrefix = VerificationCodeConstant.VERIFICATION_CODE_FORGET_KEY;
        //查询验证码是否存在,防止重复发送
        checkIsExist(keyPrefix, email);
        //生成验证码
        String code = genCode();

        //发送验证码
        MessageTemplateReplaceDTO param = MessageTemplateReplaceDTO.builder()
                .email(email)
                .code(code).build();
        if (messageTemplateService.sendMessageText(MessageTemplateEnum.TEMPLATE_2, param,email)) {
            cache(keyPrefix, email, code);
        }
    }

    @Override
    public void sendEmailCodeUpdate(Long userId) {
        String keyPrefix = VerificationCodeConstant.VERIFICATION_CODE_UPDATE_KEY;

        MemberUser user = userService.selectMemberUserById(userId);
        String email = user.getEmail();

        //查询验证码是否存在,防止重复发送
        checkIsExist(keyPrefix, email);
        //生成验证码
        String code = genCode();
        //发送验证码
        emailService.sendEmail(email, code);
        //保存验证码
        cache(keyPrefix, email, code);
    }

    @Override
    public void checkVerificationCode(String verificationCodeRegisterKey, String email, String code) {
        String key = verificationCodeRegisterKey + email;
        if (Objects.isNull(redisService.getCacheObject(key)) || !redisService.getCacheObject(key).equals(code)) {
            throw ServiceExceptionUtil.exception(VERIFICATION_CODE_ERROR);
        }
    }

    @Override
    public void deleteVerificationCode(String verificationCodeRegisterKey, String email) {
        String key = verificationCodeRegisterKey + email;
        redisService.deleteObject(key);
    }

    //生成随机验证码
    private String genCode() {
        return RandomUtil.randomNumbers(6);
    }

    //缓存验证码
    private void cache(String type, String email, String code) {
        String key = type + email;
        redisService.setCacheObject(key, code);
        redisService.expire(key, 5, TimeUnit.MINUTES);
    }

    //检查验证码是否在缓存中
    private void checkIsExist(String keyPrefix, String email) {
        if (redisService.hasKey(keyPrefix + email)) {
            throw ServiceExceptionUtil.exception(REPEAT_VERIFICATION_CODE);
        }
    }

}
